#ifndef SHADERS_HPP_INCLUDE
#define SHADERS_HPP_INCLUDE

#include "types.hpp"
#include "renderer.hpp"

class Scene;
class Renderer;
struct SampleInfo;

class Shader
{
public:
	virtual Color shade(const SampleInfo& sample, const Scene& scene, const Renderer& renderer) const;
	virtual const char* getType() = 0;
};

ostream& operator<<(ostream& os, const Shader& dt);

class SurfaceShader : public Shader
{
};

class ConstShader : public SurfaceShader
{
private:
	Color color_;
public:
	ConstShader(Color color);
	Color shade(const SampleInfo& sample, const Scene& scene, const Renderer& renderer) const;
	const char* getType();
};

class DebugShader : public SurfaceShader
{
public:
	DebugShader();
	Color shade(const SampleInfo& sample, const Scene& scene, const Renderer& renderer) const;
	const char* getType();
	void printSample(const SampleInfo* sample) const;
	void printChain(const SampleInfo* sample) const;
};

class IncidenceShader : public SurfaceShader
{
private:
	Color frontColor_;
	Color sideColor_;
public:
	IncidenceShader(Color frontColor, Color sideColor);
	Color shade(const SampleInfo& sample, const Scene& scene, const Renderer& renderer) const;
	const char* getType();
};

class OcclusionShader : public SurfaceShader
{
private:
	Color fade_;
public:
	OcclusionShader(Color fade);
	Color shade(const SampleInfo& sample, const Scene& scene, const Renderer& renderer) const;
	const char* getType();
};

class MirrorShader : public SurfaceShader
{
private:
	Color fade_;
public:
	MirrorShader(Color fade);
	Color shade(const SampleInfo& sample, const Scene& scene, const Renderer& renderer) const;
	const char* getType();
};

#endif //SHADERS_HPP_INCLUDE
